﻿using System;
using System.Text;
using SmartHRMS.Model.Account;
using SmartHRMS.Infrastructure;
using StructureMap;
using SmartHRMS.Model;
using SmartHRMS.Services;
using SmartHRMS.CustomExceptions.Infrastructure;
using System.Collections.Generic;

namespace SmartHRMS.Presentation.Account
{
    public class RolePresenter
    {
        private IPrincipalService _ICustomPrincipalService = ObjectFactory.GetInstance<IPrincipalService>();
        private IRoleView view;
        private IRoleService roleService;
        public Role role;
        private Mode mode;

        public RolePresenter(IRoleView view)
        : this(ObjectFactory.GetInstance<IRoleService>(), view)
        {
        }

        public RolePresenter(IRoleService roleService, IRoleView view)
        {
            this.view = view;
            this.roleService = roleService;
        }

        private void setButtonText()
        {
            if (mode == Mode.Add)
            {
                view.SaveButtonText = "Save";
            }
            else
            {
                view.SaveButtonText = "Update";
            }
        }

        private void setTitleText()
        {
            if (mode == Mode.Add)
            {
                view.ViewTitle("Add");
            }
            else
            {
                view.ViewTitle("Edit");
            }
        }

        private void ClearInfoAndErrorMessages()
        {
            view.ErrorMessage(string.Empty);
            view.InfoMessage(string.Empty);
            view.WarringMessage(string.Empty);
        }

        private void DisplayErrorsIn(Role role)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("There were some problems when trying to save this user information:");
            sb.Append(Environment.NewLine);
            sb.Append(Environment.NewLine);

            foreach (BrokenRule brokenRule in role.GetBrokenRules())
            {
                sb.Append(brokenRule.Rule);
                sb.Append(Environment.NewLine);
                view.ErrorMessage(sb.ToString());
            }
        }

        public void ClearView()
        {
            view.Name = "";
            view.InsertedBy = "";
            view.InsertedDate = "";
            view.UpdatedBy = "";
            view.UpdatedDate = "";
            view.InsertedByName = "";
            view.UpdatedByName = "";
        }

        /// <summary>
        /// Updates the the presentation view.
        /// </summary>
        /// <param name="role">The role object.</param>
        private void UpdateView(Role role)
        {
            if (role != null)
            {
                view.Permission = new List<string>();

                view.Name = role.Name;
                CommonFields commonFields = new CommonFields(
                    role.CommonFields.InsertedBy,
                    role.CommonFields.InsertedDate,
                    role.CommonFields.UpdatedBy,
                    role.CommonFields.UpdatedDate);
                view.InsertedBy = commonFields.InsertedBy.ToString();
                view.InsertedDate = commonFields.InsertedDate;
                view.UpdatedBy = commonFields.UpdatedBy.ToString();
                view.UpdatedDate = commonFields.UpdatedDate;
                if (commonFields.UpdatedBy != Guid.Empty && !string.IsNullOrEmpty(commonFields.UpdatedBy.ToString()))
                {
                    User userActivity = new User();
                    UserService userService = ObjectFactory.GetInstance<UserService>();
                    userActivity = userService.FindBy(commonFields.InsertedBy);
                    view.InsertedByName = userActivity.UserName;
                    userActivity = userService.FindBy(commonFields.UpdatedBy);
                    view.UpdatedByName = userActivity.UserName;
                }
                else
                {
                    User userActivity = new User();
                    UserService userService = ObjectFactory.GetInstance<UserService>();
                    userService.FindBy(commonFields.InsertedBy);
                    view.InsertedByName = userActivity.UserName;
                }

                //load the assigned permissions from model.
                foreach (Permission pr in role.Permission)
                {
                    view.Permission.Add(pr.PermissionId.ToString());
                }
            }
        }

        /// <summary>
        /// Updates the model.
        /// </summary>
        /// <param name="role">The user object.</param>
        private void UpdateModel(Role role)
        {
            role.Name = view.Name;
            if (mode == Mode.Add)
            {
                CommonFields commonFields = new CommonFields(
                    new Guid(_ICustomPrincipalService.User.UserId.ToString()),
                    DateTime.Now.ToString(),
                    new Guid(_ICustomPrincipalService.User.UserId.ToString()),
                    DateTime.Now.ToString());
                role.CommonFields = commonFields;

                //load the assigned permissions from user interface.
                foreach (string pr in view.Permission)
                {
                    string[] splitPermissionIdAndKey = pr.Split(',');
                    string permission=splitPermissionIdAndKey[0];
                    string permissionKey = splitPermissionIdAndKey[1];
                    Permission tempPermission = new Permission(new Guid(permission), permissionKey);
                    role.Permission.Add(tempPermission);
                }
            }
            else
            {
                CommonFields commonFields = new CommonFields(
                    new Guid(_ICustomPrincipalService.User.UserId.ToString()),
                    DateTime.Now.ToString());
                role.CommonFields.InsertedBy = role.CommonFields.InsertedBy;
                role.CommonFields.InsertedDate = role.CommonFields.InsertedDate;
                role.CommonFields.UpdatedBy = commonFields.UpdatedBy;
                role.CommonFields.UpdatedDate = commonFields.UpdatedDate;

                //load the assigned permissions from user interface.
                foreach (string pr in view.Permission)
                {
                    string[] splitPermissionIdAndKey = pr.Split(',');
                    string permission = splitPermissionIdAndKey[0];
                    string permissionKey = splitPermissionIdAndKey[1];
                    Permission tempPermission = new Permission(new Guid(permission), permissionKey);
                    role.Permission.Add(tempPermission);
                }
            }
        }

        private Role GetSelectedRoleDetail()
        {
            if (role == null)
            {
                if (view.RoleId == Guid.Empty)
                {
                    //Add mode
                    role = new Role();
                    mode = Mode.Add;
                    role.Mode = Mode.Add;
                }
                else
                {
                    // Edit mode
                    role = this.roleService.FindBy(this.view.RoleId);
                    mode = Mode.Edit;
                    role.Mode = Mode.Edit;
                }
            }
            return role;
        }

        public void Display()
        {
            Role role = GetSelectedRoleDetail();

            ClearInfoAndErrorMessages();
            setButtonText();
            setTitleText();

            if (role.RoleId == Guid.Empty)
            {
                //  view.WarringMessage(string.Format("Could not find details from role information with Id of {0}.", view.RoleId));
            }
            else
            {
                if (mode == Mode.Edit)
                    role.Mode = Mode.Edit;
                UpdateView(role);
            }
        }

        public void SaveRole()
        {
            Role role = GetSelectedRoleDetail();
            ClearInfoAndErrorMessages();
            try
            {
                UpdateModel(role);
                if (role.GetBrokenRules().Count == 0)
                {
                    try
                    {  
                        this.roleService.Save(role);

                        if (mode == Mode.Add)
                        {
                            this.view.InfoMessage(String.Format("Role information '{0}' has been added.", role.Name));
                            this.ClearView();
                        }
                        else
                        {
                            this.view.InfoMessage(String.Format("Role information has been updated successfully."));
                        }
                    }
                    catch (Exception ex)
                    {
                        string exceptionMessage = String.Format("A problem occurred while saving company information '{0}'. {1}{2}", role.Name, Environment.NewLine, ex.Message);
                        view.ErrorMessage(exceptionMessage);
                    }
                }
                else
                {
                    DisplayErrorsIn(role);
                }
            }
            catch (ValueObjectValidationException ex)
            {
                view.ErrorMessage(ex.Message);
            }
        }
    }
}
